package service

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gorilla/websocket"
	"go.uber.org/zap"
	"net"
	"seichat/dao"
	"seichat/models"
	"strconv"
	"sync"
)

func (m *InMemoryMessageService) BrodMsg(data []byte) {
	m.uDPSendChan <- data
}

// UdpSendProc 完成upd数据发送, 连接到udp服务端，将channel中的消息体，写入udp服务端
func (m *InMemoryMessageService) UdpSendProc() {
	udpConn, err := net.DialUDP("udp", nil, &net.UDPAddr{
		//192.168.31.147
		IP:   net.IPv4(127, 0, 0, 1),
		Port: 3000,
		Zone: "",
	})
	if err != nil {
		zap.S().Info("拨号udp端口失败", err)
		return
	}

	defer udpConn.Close()

	for {
		select {
		case data := <-m.uDPSendChan:
			_, err := udpConn.Write(data)
			if err != nil {
				zap.S().Error("UDP写入失败", zap.Error(err))
				return
			}
		}
	}
}

// UpdRecProc 完成udp数据的接收，启动udp服务，获取udp客户端的写入的消息
func (m *InMemoryMessageService) UpdRecProc() {
	udpConn, err := net.ListenUDP("udp", &net.UDPAddr{
		IP:   net.IPv4(127, 0, 0, 1),
		Port: 3000,
	})
	if err != nil {
		zap.S().Info("监听udp端口失败", err)
		return
	}

	defer udpConn.Close()

	for {
		var buf [1024]byte
		n, err := udpConn.Read(buf[0:])
		if err != nil {
			zap.S().Error("UDP读取失败", zap.Error(err))
			return
		}

		m.dispatch(buf[0:n])
	}
}

// dispatch 解析消息，聊天类型判断
func (m *InMemoryMessageService) dispatch(data []byte) {
	//解析消息
	msg := models.Message{}
	err := json.Unmarshal(data, &msg)
	if err != nil {
		zap.S().Error("消息解析失败", err)
		return
	}

	//判断消息类型
	switch msg.Type {
	case 1: //私聊
		m.sendMsg(msg.TargetId, data)
	case 2: //群发
		_, err = m.sendGroupMsg(uint(msg.FormId), uint(msg.TargetId), data)
		if err != nil {
			return
		}
	}
}

// sendMs 向用户单聊发送消息
func (m *InMemoryMessageService) sendMsg(id int64, msg []byte) {
	m.mu.Lock()
	node, ok := m.clients[id]
	m.mu.Unlock()

	if !ok {
		zap.S().Info("userID没有对应的node")
		return
	}

	zap.S().Info("targetID:", id, "node:", node)
	if ok {
		node.DataQueue <- msg
	}
}

// SendGroupMsg 群发逻辑
func (m *InMemoryMessageService) sendGroupMsg(formId, target uint, data []byte) (int, error) {
	// 获取群组成员ID列表
	userIDs, err := m.relationSvc.FindUsersIdByGroupId(context.Background(), formId)
	if err != nil {
		zap.S().Error("获取群组成员失败", zap.Error(err))
		return -1, err
	}

	// 向每个成员发送消息（排除发送者自己）
	for _, userId := range *userIDs {
		// 转换为int64进行比较
		if int64(formId) != int64(userId) {
			optCtx := context.WithValue(context.Background(), "trace_id", "group_msg_"+strconv.Itoa(int(formId)))
			if err := m.sendMsgAndSave(optCtx, int64(userId), data); err != nil {
				zap.S().Warn("群发消息失败", zap.Int64("targetID", int64(userId)), zap.Error(err))
			}
		}
	}
	return 0, nil
}

// sendMsgAndSave 发送并存储消息，支持上下文追踪
func (m *InMemoryMessageService) sendMsgAndSave(ctx context.Context, userId int64, msg []byte) error {
	m.mu.RLock()
	node, ok := m.clients[userId] // 检查目标用户是否在线
	m.mu.RUnlock()

	jsonMsg := models.Message{}
	if err := json.Unmarshal(msg, &jsonMsg); err != nil {
		zap.S().Error("消息反序列化失败", zap.Error(err))
		return err
	}

	targetIdStr := strconv.Itoa(int(userId))
	userIdStr := strconv.Itoa(int(jsonMsg.FormId))

	// 如果用户在线，通过WebSocket发送消息
	if ok {
		node.DataQueue <- msg
	}

	// 构建Redis存储键值
	var key string
	if userId > jsonMsg.FormId {
		key = "msg_" + userIdStr + "_" + targetIdStr
	} else {
		key = "msg_" + targetIdStr + "_" + userIdStr
	}

	// 保存消息到Redis
	if err := m.messageDao.SendMsgAndSave(ctx, key, msg); err != nil {
		zap.S().Error("消息持久化失败", zap.Error(err))
		return err
	}

	return nil
}

// MessageService 负责管理客户端连接
type MessageService interface {
	Register(id int64, node *models.Node)
	Unregister(id int64)
	Get(id int64) (*models.Node, bool)
	RecProc(node *models.Node)
	SendProc(node *models.Node)
	BrodMsg(data []byte)
	SendRedisMsg(ctx context.Context, key string, start int64, end int64, isRev bool) ([]string, error)
}

// InMemoryMessageService 是 MessageService 的一个内存实现
type InMemoryMessageService struct {
	clients     map[int64]*models.Node
	mu          sync.RWMutex
	uDPSendChan chan []byte
	relationSvc RelationService
	messageDao  dao.MessageDao
}

// NewInMemoryConnectionManager 修改构造函数
func NewInMemoryConnectionManager(messageDao dao.MessageDao, relationSvc RelationService) *InMemoryMessageService {
	manager := &InMemoryMessageService{
		clients:     make(map[int64]*models.Node),
		uDPSendChan: make(chan []byte, 1024),
		relationSvc: relationSvc,
		messageDao:  messageDao,
	}

	// 启动UDP协程
	go manager.UdpSendProc()
	go manager.UpdRecProc()
	return manager
}

func (m *InMemoryMessageService) SendRedisMsg(ctx context.Context, key string, start int64, end int64, isRev bool) ([]string, error) {
	res, err := m.messageDao.RedisMsg(ctx, key, start, end, isRev)
	if err != nil {
		zap.S().Warnw("获取redis消息失败", "key", key)
		return nil, err
	}
	return res, nil
}
func (m *InMemoryMessageService) Register(id int64, node *models.Node) {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.clients[id] = node
}

func (m *InMemoryMessageService) Unregister(id int64) {
	m.mu.Lock()
	defer m.mu.Unlock()
	delete(m.clients, id)
}

func (m *InMemoryMessageService) Get(id int64) (*models.Node, bool) {
	m.mu.RLock()
	defer m.mu.RUnlock()
	node, ok := m.clients[id]
	return node, ok
}

// RecProc 接收一个 MessageService 实现作为参数
func (m *InMemoryMessageService) RecProc(node *models.Node) {
	for {
		_, data, err := node.Conn.ReadMessage()
		if err != nil {
			zap.S().Error("读取消息失败", err)
			return
		}
		m.BrodMsg(data)
	}
}

// SendProc 监听node的DataQueue
func (m *InMemoryMessageService) SendProc(node *models.Node) {
	for {
		select {
		case data := <-node.DataQueue:
			err := node.Conn.WriteMessage(websocket.TextMessage, data)
			if err != nil {
				zap.S().Info("写入消息失败", err)
				return
			}
			fmt.Println("数据发送socket成功")
		}
	}
}
